fix(stripe): trim whitespace from webhook secret and signature#565
Conversation
The STRIPE_WEBHOOK_SECRET stored in Secret Manager had a trailing newline, which made stripe.webhooks.constructEvent reject every live event with a signature-verification error (400). No credits were granted to any paying customer, silently. Trim both STRIPE_WEBHOOK_SECRET and the stripe-signature header before verification (mirrors validateAndNormalizeStripeSecretKey for the API key). Add a regression test with a newline-suffixed secret and padded signature, and document STRIPE_WEBHOOK_SECRET in .env.example as a Secret-Manager value that must have no trailing whitespace. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
There was a problem hiding this comment.
Pull request overview
Fixes Stripe webhook signature verification failures caused by stray whitespace (notably trailing newlines) in STRIPE_WEBHOOK_SECRET and potentially padded stripe-signature headers, preventing dropped events and missed credit grants.
Changes:
- Trim
STRIPE_WEBHOOK_SECRETbefore callingstripe.webhooks.constructEvent. - Trim and validate the
stripe-signatureheader before verification. - Add a regression test covering newline-suffixed secret and padded signature; document
STRIPE_WEBHOOK_SECRETusage infunctions/.env.example.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| functions/src/stripeWebhook.ts | Trims webhook secret and signature header prior to Stripe event verification. |
| functions/src/stripeWebhook.test.ts | Adds regression test asserting trimmed values are passed to constructEvent. |
| functions/.env.example | Documents STRIPE_WEBHOOK_SECRET and warns against trailing whitespace/newlines. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Follow-up ticket for the next agent: end-to-end pack-purchase smoke test once the front-end deploy lands, and investigation of the analytics gaps (no GA4 purchase/conversion event; BigQuery export vs. Connections page). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Incident
The first paying customer paid $10 but received no credits (stuck at signup credits,
freetier). Root cause: theSTRIPE_WEBHOOK_SECRETvalue in Secret Manager had a trailing newline. It was passed raw intostripe.webhooks.constructEvent, so Stripe rejected every live webhook with a signature-verification error (400) — the credit-grant path never ran, silently, for all payers.Stripe's own error confirmed it: "the provided signing secret contains whitespace…".
Fix
STRIPE_WEBHOOK_SECRETand thestripe-signatureheader before verification (mirrors the existingvalidateAndNormalizeStripeSecretKeyused for the API key).constructEvent). Red→green confirmed; fullstripeWebhooksuite passes (27/27), build clean.STRIPE_WEBHOOK_SECRETinfunctions/.env.exampleas a Secret-Manager value that must carry no trailing whitespace.Operational steps done outside this PR (prod)
STRIPE_WEBHOOK_SECRETcleanly (rolled the endpoint's signing secret) and redeployedstripeWebhook. Verified the deployed function accepts a correctly-signed request (200).recurring(turning pack buyers into $10/mo subscribers). Created a one-time price, repointedSTRIPE_CREDIT_PACK_PRICE_ID(backend + client env), archived the old price. Client web/OTA rollout in progress.🤖 Generated with Claude Code